home *** CD-ROM | disk | FTP | other *** search
- #ifdef __cplusplus
- extern "C" {
- #endif
-
- #include <mach/mach_traps.h>
- #include <mach/vm_map.h>
-
- #ifdef __cplusplus
- }
- #endif
-
- #include <Carbon/Carbon.h>
- #include <CoreServices/CoreServices.h>
- #include <sys/mman.h>
- #include <sys/ptrace.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include "MachOUtils.h"
-
-
-
- #ifdef __cplusplus
- extern "C" {
- #endif
-
- int main(int argc,char *argv[]);
- char *SetAppDir(char *dst,char *argv0);
- char *BuildSubPath(char *dst,char *path,char *subpath);
- mach_port_t GetFinderTask(ProcessSerialNumber *psn,pid_t *pid);
- void SendPingAppleEvent(ProcessSerialNumber *psn);
- UInt32 ReadTaskUInt32(mach_port_t task,UInt32 addr);
- void WriteTaskUInt32(mach_port_t task,UInt32 addr,UInt32 data);
-
- #ifdef __cplusplus
- }
- #endif
-
-
-
- #define kPowerPlantPath "/System/Library/PrivateFrameworks/PowerPlant.framework/PowerPlant"
- #define kLibSystemPath "/usr/lib/libSystem.B.dylib"
- #define kFinderPatchSubPath "Resources/FinderPatch"
- #define kFinderPatchEntry "_Initialize"
-
-
-
- #define LI32(op,data) do { UInt32 *_op = (UInt32*)(op),_data = (UInt32)(data); \
- _op[0] = (_op[0] & 0xFFFF0000) | ((_data >> 16) & 0xFFFF); \
- _op[1] = (_op[1] & 0xFFFF0000) | (_data & 0xFFFF); \
- } while(false)
-
-
-
- UInt32 gLibSystem_DYLDFuncLookUpVector = 4 + (UInt32)FindSectionAddress(kLibSystemPath,"__DATA","__dyld");
- UInt32 gPowerPlant_AEProcessAppleEventVector = (UInt32)FindSymbolAddress(kPowerPlantPath,"_AEProcessAppleEvent");
- char gAppPath[PATH_MAX];
- char gFinderPatchPath[PATH_MAX];
- UInt32 gPatchCode[] = {
- 0x7C0802A6, 0xBE61FFCC, 0x90010008, 0x9421FF80, 0x90610098, 0x3EA00000, 0x62B50000, 0x3EC00000,
- 0x62D60000, 0x3EE00000, 0x62F70000, 0x3F000000, 0x63180000, 0x3F200000, 0x63390000, 0x3F400000,
- 0x635A0000, 0x3F600000, 0x637B0000, 0x3F800000, 0x639C0000, 0x3FA00000, 0x63BD0000, 0x3FC00000,
- 0x63DE0000, 0x3FE00000, 0x63FF0000, 0x92B60000, 0x7FE803A6, 0x7FC3F378, 0x38810038, 0x4E800021,
- 0x83C10038, 0x7FC803A6, 0x7FA3EB78, 0x38810038, 0x38A1003C, 0x4E800021, 0x83A10038, 0x7FC803A6,
- 0x7F83E378, 0x38810038, 0x38A1003C, 0x4E800021, 0x83810038, 0x7FC803A6, 0x7F63DB78, 0x38810038,
- 0x38A1003C, 0x4E800021, 0x83610038, 0x7FC803A6, 0x7F43D378, 0x38810038, 0x38A1003C, 0x4E800021,
- 0x83410038, 0x7FC803A6, 0x7F23CB78, 0x38810038, 0x38A1003C, 0x4E800021, 0x83210038, 0x7FA803A6,
- 0x7F03C378, 0x38810038, 0x4E800021, 0x82810038, 0x7F8803A6, 0x7E83A378, 0x7F04C378, 0x38A00002,
- 0x4E800021, 0x7C731B78, 0x7F6803A6, 0x7E83A378, 0x4E800021, 0x7F4803A6, 0x7E639B78, 0x7EE4BB78,
- 0x4E800021, 0x7F2803A6, 0x4E800021, 0x7C6803A6, 0x4E800021, 0x80610098, 0x7EA903A6, 0x80010088,
- 0x38210080, 0x7C0803A6, 0xBA61FFCC, 0x4E800420 };
-
-
-
- int main(int argc,char *argv[])
- {
- ProcessSerialNumber finderPSN;
- pid_t finderPID;
- mach_port_t finderTask;
- vm_address_t target_patch,local_patch;
- char *str;
- OSStatus err;
-
- if (gLibSystem_DYLDFuncLookUpVector <= 4) {
- fprintf(stderr,"Unresolved vector: LibSystem_DYLDFuncLookUp");
- exit(1);
- }
-
- if (gPowerPlant_AEProcessAppleEventVector == NULL) {
- fprintf(stderr,"Unresolved vector: PowerPlant_AEProcessAppleEvent");
- exit(1);
- }
-
- SetAppDir(gAppPath,argv[0]);
- BuildSubPath(gFinderPatchPath,gAppPath,kFinderPatchSubPath);
-
- finderTask = GetFinderTask(&finderPSN,&finderPID);
- if (finderTask == MACH_PORT_NULL)
- {
- fprintf(stderr,"Unable to locate the Finder process, quitting.\n");
- exit(1);
- }
-
- // Ensure AEProcessAppleEvent is bound.
- SendPingAppleEvent(&finderPSN);
-
- // Stop the target so we can safely patch it.
- if (ptrace(PT_ATTACH,finderPID,NULL,0) != 0)
- {
- fprintf(stderr,"ptrace(PT_ATTACH,finder) failed: %08lX, %s\n",(UInt32)errno,strerror(errno));
- exit(1);
- }
-
- // Allocate a page in the target process to hold our patch.
- target_patch = NULL;
- err = vm_allocate(finderTask,&target_patch,4096,VM_PROT_ALL);
- if (err != KERN_SUCCESS)
- {
- errno = err;
- perror("vm_allocate");
- exit(1);
- }
-
- err = vm_protect(finderTask,target_patch,4096,false,VM_PROT_ALL);
- if (err != KERN_SUCCESS)
- {
- errno = err;
- perror("vm_protect");
- exit(1);
- }
-
- // Allocate a page in our process to generate the patch.
- local_patch = NULL;
- err = vm_allocate(mach_task_self(),&local_patch,4096,VM_PROT_ALL);
- if (err != KERN_SUCCESS)
- {
- errno = err;
- perror("vm_allocate");
- exit(1);
- }
-
- // Generate the patch.
- str = (char*)local_patch + sizeof(gPatchCode);
- strcpy(str + (0 * 256),kFinderPatchEntry);
- strcpy(str + (1 * 256),gFinderPatchPath);
- strcpy(str + (2 * 256),"_NSAddressOfSymbol");
- strcpy(str + (3 * 256),"_NSLookupSymbolInModule");
- strcpy(str + (4 * 256),"_NSDestroyObjectFileImage");
- strcpy(str + (5 * 256),"_NSLinkModule");
- strcpy(str + (6 * 256),"_NSCreateObjectFileImageFromFile");
- strcpy(str + (7 * 256),"__dyld_lookup_and_bind");
-
- str = (char*)target_patch + sizeof(gPatchCode);
- BlockMoveData(gPatchCode,(void*)local_patch,sizeof(gPatchCode));
- LI32(&((UInt32*)local_patch)[5],ReadTaskUInt32(finderTask,gPowerPlant_AEProcessAppleEventVector));
- LI32(&((UInt32*)local_patch)[7],gPowerPlant_AEProcessAppleEventVector);
- LI32(&((UInt32*)local_patch)[9],str + (0 * 256));
- LI32(&((UInt32*)local_patch)[11],str + (1 * 256));
- LI32(&((UInt32*)local_patch)[13],str + (2 * 256));
- LI32(&((UInt32*)local_patch)[15],str + (3 * 256));
- LI32(&((UInt32*)local_patch)[17],str + (4 * 256));
- LI32(&((UInt32*)local_patch)[19],str + (5 * 256));
- LI32(&((UInt32*)local_patch)[21],str + (6 * 256));
- LI32(&((UInt32*)local_patch)[23],str + (7 * 256));
- LI32(&((UInt32*)local_patch)[25],ReadTaskUInt32(finderTask,gLibSystem_DYLDFuncLookUpVector));
-
- // Transfer patch into the target process.
- err = vm_write(finderTask,target_patch,local_patch,4096);
- if (err != KERN_SUCCESS)
- {
- errno = err;
- perror("vm_write");
- exit(1);
- }
-
- // Patch the vector in the target process (ie, SetTrapAddress).
- WriteTaskUInt32(finderTask,gPowerPlant_AEProcessAppleEventVector,(UInt32)target_patch);
-
- // Deallocate our local copy of the patch.
- err = vm_deallocate(mach_task_self(),local_patch,4096);
- if (err != KERN_SUCCESS)
- {
- errno = err;
- perror("vm_deallocate");
- exit(1);
- }
-
- // Resume the target. Since this sometimes returns EBUSY just for the hell of it,
- // we sleep and retry until it succeeds, or fails with a nastier error.
- while(true)
- {
- if (ptrace(PT_DETACH,finderPID,NULL,0) != 0)
- {
- if (errno == EBUSY)
- {
- usleep(1000);
- continue;
- }
-
- fprintf(stderr,"ptrace(PT_DETACH,finder) failed: %08lX, %s\n",(UInt32)errno,strerror(errno));
- exit(1);
- }
-
- break;
- }
-
- // Ensure AEProcessAppleEvent is called.
- SendPingAppleEvent(&finderPSN);
- return 0;
- }
-
-
-
- char *SetAppDir(char *dst,char *argv0)
- {
- FSRef ref;
- int len;
- OSStatus err;
-
- // Build a fully qualified path by combining the CWD and the dirname
- // portion of argv[0]. We also resolve any .. components, but since
- // unix doesn't provide an inverse parth lookup function, we have to
- // use the CoreService's File Manager APIs.
- for (len = strlen(argv0);((len > 0) && (argv0[len - 1] != '/'));len -= 1) { }
- sprintf(dst,"%.*s",len,argv0);
-
- err = FSPathMakeRef((UInt8*)dst,&ref,NULL);
- if (err != noErr)
- {
- fprintf(stderr,"FSPathMakeRef failed: %s\n",strerror(err));
- exit(1);
- }
-
- err = FSRefMakePath(&ref,(UInt8*)dst,PATH_MAX);
- if (err != noErr)
- {
- fprintf(stderr,"FSRefMakePath failed: %s\n",strerror(err));
- exit(1);
- }
-
- if (chdir(dst))
- {
- perror("chdir failed");
- exit(1);
- }
-
- printf("CWD: %s\n",dst);
- return dst;
- }
-
-
-
- char *BuildSubPath(char *dst,char *path,char *subpath)
- {
- FSRef ref;
- int len;
- OSStatus err;
-
- for (len = strlen(path);((len > 0) && (path[len - 1] != '/'));len -= 1) { }
- sprintf(dst,"%.*s%s",len,path,subpath);
-
- err = FSPathMakeRef((UInt8*)dst,&ref,NULL);
- if (err != noErr)
- {
- fprintf(stderr,"FSPathMakeRef failed: %s\n",strerror(err));
- exit(1);
- }
-
- err = FSRefMakePath(&ref,(UInt8*)dst,PATH_MAX);
- if (err != noErr)
- {
- fprintf(stderr,"FSRefMakePath failed: %s\n",strerror(err));
- exit(1);
- }
-
- printf("path: %s\n",dst);
- return dst;
- }
-
-
-
- mach_port_t GetFinderTask(ProcessSerialNumber *psn,pid_t *pid)
- {
- ProcessInfoRec pinfo;
- Str255 name;
- FSSpec spec;
- mach_port_t task;
- OSStatus err;
-
- psn->highLongOfPSN = 0;
- psn->lowLongOfPSN = kNoProcess;
- while(GetNextProcess(psn) == noErr)
- {
- memset(&pinfo,0,sizeof(ProcessInfoRec));
- pinfo.processInfoLength = sizeof(ProcessInfoRec);
- pinfo.processName = name;
- pinfo.processAppSpec = &spec;
- GetProcessInformation(psn,&pinfo);
- if ((pinfo.processSignature != 'MACS') || (pinfo.processType != 'FNDR'))
- continue;
-
- err = GetProcessPID(psn,pid);
- if (err != noErr)
- {
- errno = err;
- perror("GetProcessPID");
- exit(1);
- }
-
- err = task_for_pid(mach_task_self(),*pid,&task);
- if (err != noErr)
- {
- errno = err;
- perror("task_for_pid");
- exit(1);
- }
-
- return task;
- }
-
- return MACH_PORT_NULL;
- }
-
-
-
- void SendPingAppleEvent(ProcessSerialNumber *psn)
- {
- AEAddressDesc addr;
- AppleEvent event,reply;
- OSStatus err;
-
- err = AECreateDesc(typeProcessSerialNumber,(Ptr)psn,sizeof(ProcessSerialNumber),&addr);
- if (err == noErr)
- {
- err = AECreateAppleEvent('hack','ping',&addr,kAutoGenerateReturnID,kAnyTransactionID,&event);
- if (err == noErr)
- {
- err = AESend(&event,&reply,kAEWaitReply + kAENeverInteract,kAEHighPriority,kNoTimeOut,NULL,NULL);
- if (err == noErr)
- AEDisposeDesc(&reply);
-
- AEDisposeDesc(&event);
- }
-
- AEDisposeDesc(&addr);
- }
- }
-
-
-
- UInt32 ReadTaskUInt32(mach_port_t task,UInt32 addr)
- {
- vm_address_t data;
- unsigned int size;
- UInt32 value;
- OSStatus err;
-
- err = vm_read(task,(vm_address_t)(addr & ~4095),4096,&data,&size);
- if (err != KERN_SUCCESS)
- {
- errno = err;
- perror("vm_read");
- exit(1);
- }
-
- value = *(UInt32*)(data + (addr & 4095));
-
- err = vm_deallocate(mach_task_self(),data,size);
- if (err != KERN_SUCCESS)
- {
- errno = err;
- perror("vm_deallocate");
- exit(1);
- }
-
- return value;
- }
-
-
-
- void WriteTaskUInt32(mach_port_t task,UInt32 addr,UInt32 value)
- {
- vm_address_t data;
- unsigned int size;
- OSStatus err;
-
- err = vm_read(task,(vm_address_t)(addr & ~4095),4096,&data,&size);
- if (err != KERN_SUCCESS)
- {
- errno = err;
- perror("vm_read");
- exit(1);
- }
-
- *(UInt32*)(data + (addr & 4095)) = value;
-
- err = vm_write(task,(vm_address_t)(addr & ~4095),data,size);
- if (err != KERN_SUCCESS)
- {
- errno = err;
- perror("vm_write");
- exit(1);
- }
-
- err = vm_deallocate(mach_task_self(),data,size);
- if (err != KERN_SUCCESS)
- {
- errno = err;
- perror("vm_deallocate");
- exit(1);
- }
- }
-